package com.zenithmind.common.utils;

import com.zenithmind.common.exception.BusinessException;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 业务规则验证工具类 - 遵循单一职责原则
 * 只负责业务规则验证相关的工具方法
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
public class BusinessRuleValidator {

    /**
     * 验证群组成员数量限制
     * 
     * @param currentCount 当前成员数
     * @param maxCount 最大成员数
     * @param addCount 要添加的成员数
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateGroupMemberLimit(int currentCount, int maxCount, int addCount) {
        if (currentCount + addCount > maxCount) {
            throw new BusinessException("群组成员数量已达上限，最多允许" + maxCount + "人");
        }
    }

    /**
     * 验证用户是否在群组中
     * 
     * @param isInGroup 是否在群组中
     * @param operation 操作名称
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateUserInGroup(boolean isInGroup, String operation) {
        if (!isInGroup) {
            throw new BusinessException("用户不在群组中，无法" + operation);
        }
    }

    /**
     * 验证用户是否不在群组中
     * 
     * @param isInGroup 是否在群组中
     * @param operation 操作名称
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateUserNotInGroup(boolean isInGroup, String operation) {
        if (isInGroup) {
            throw new BusinessException("用户已在群组中，无法" + operation);
        }
    }

    /**
     * 验证群组权限
     * 
     * @param userRole 用户角色（1-群主，2-管理员，3-成员）
     * @param requiredRole 所需角色
     * @param operation 操作名称
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateGroupPermission(Integer userRole, Integer requiredRole, String operation) {
        if (userRole == null || userRole > requiredRole) {
            String roleName = getRoleName(requiredRole);
            throw new BusinessException("只有" + roleName + "才能" + operation);
        }
    }

    /**
     * 验证群组状态
     * 
     * @param groupStatus 群组状态（1-正常，2-禁用，3-解散）
     * @param operation 操作名称
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateGroupStatus(Integer groupStatus, String operation) {
        if (groupStatus == null || groupStatus != 1) {
            throw new BusinessException("群组状态异常，无法" + operation);
        }
    }

    /**
     * 验证用户状态
     * 
     * @param userStatus 用户状态（1-正常，2-禁言，3-踢出）
     * @param operation 操作名称
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateUserStatus(Integer userStatus, String operation) {
        if (userStatus == null || userStatus == 3) {
            throw new BusinessException("用户已被踢出，无法" + operation);
        }
        if (userStatus == 2) {
            throw new BusinessException("用户已被禁言，无法" + operation);
        }
    }

    /**
     * 验证消息发送权限
     * 
     * @param isAllMuted 是否全员禁言
     * @param userRole 用户角色
     * @param userStatus 用户状态
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateMessageSendPermission(Boolean isAllMuted, Integer userRole, Integer userStatus) {
        // 检查用户状态
        validateUserStatus(userStatus, "发送消息");
        
        // 检查全员禁言
        if (isAllMuted != null && isAllMuted) {
            // 只有群主和管理员可以在全员禁言时发送消息
            if (userRole == null || userRole > 2) {
                throw new BusinessException("群组已开启全员禁言，无法发送消息");
            }
        }
    }

    /**
     * 验证好友关系
     * 
     * @param isFriend 是否为好友
     * @param operation 操作名称
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateFriendship(boolean isFriend, String operation) {
        if (!isFriend) {
            throw new BusinessException("非好友关系，无法" + operation);
        }
    }

    /**
     * 验证时间范围
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        if (startTime != null && endTime != null && startTime.isAfter(endTime)) {
            throw new BusinessException("开始时间不能晚于结束时间");
        }
    }

    /**
     * 验证操作频率限制
     * 
     * @param lastOperationTime 上次操作时间
     * @param intervalSeconds 间隔秒数
     * @param operation 操作名称
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateOperationFrequency(LocalDateTime lastOperationTime, int intervalSeconds, String operation) {
        if (lastOperationTime != null) {
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime allowedTime = lastOperationTime.plusSeconds(intervalSeconds);
            if (now.isBefore(allowedTime)) {
                throw new BusinessException(operation + "过于频繁，请稍后再试");
            }
        }
    }

    /**
     * 验证批量操作数量限制
     * 
     * @param count 操作数量
     * @param maxCount 最大数量
     * @param operation 操作名称
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateBatchOperationLimit(int count, int maxCount, String operation) {
        if (count > maxCount) {
            throw new BusinessException("批量" + operation + "数量不能超过" + maxCount);
        }
    }

    /**
     * 验证文件上传权限
     * 
     * @param fileSize 文件大小
     * @param maxFileSize 最大文件大小
     * @param allowedTypes 允许的文件类型
     * @param mimeType 文件MIME类型
     * @throws BusinessException 验证失败时抛出
     */
    public static void validateFileUpload(Long fileSize, Long maxFileSize, List<String> allowedTypes, String mimeType) {
        // 验证文件大小
        if (fileSize != null && maxFileSize != null && fileSize > maxFileSize) {
            throw new BusinessException("文件大小超过限制，最大允许" + formatFileSize(maxFileSize));
        }
        
        // 验证文件类型
        if (allowedTypes != null && !allowedTypes.isEmpty() && mimeType != null) {
            boolean typeAllowed = allowedTypes.stream().anyMatch(type -> mimeType.startsWith(type));
            if (!typeAllowed) {
                throw new BusinessException("不支持的文件类型");
            }
        }
    }

    /**
     * 获取角色名称
     * 
     * @param role 角色代码
     * @return 角色名称
     */
    private static String getRoleName(Integer role) {
        if (role == null) return "未知";
        switch (role) {
            case 1: return "群主";
            case 2: return "管理员";
            case 3: return "成员";
            default: return "未知";
        }
    }

    /**
     * 格式化文件大小
     * 
     * @param size 文件大小（字节）
     * @return 格式化后的大小
     */
    private static String formatFileSize(long size) {
        if (size <= 0) return "0 B";
        String[] units = {"B", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double fileSize = size;
        while (fileSize >= 1024 && unitIndex < units.length - 1) {
            fileSize /= 1024;
            unitIndex++;
        }
        return String.format("%.1f %s", fileSize, units[unitIndex]);
    }
}
